from django.shortcuts import render
from rest_framework.pagination import PageNumberPagination
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.viewsets import ModelViewSet
from course.sers import *
from django.db.models import Q
from django.http import HttpResponse
from rest_framework_jwt.utils import jwt_decode_handler


# Create your views here.

class TagModelViewSet(ModelViewSet):
    queryset = Tag.objects.all()
    serializer_class = TagModelSerializer


class CoursePagination(PageNumberPagination):
    page_size_query_param = 'page_size'
    page_size = 3


class CourseModelViewSet(ModelViewSet):
    queryset = Course.objects.all()
    serializer_class = CourseModelSerializer

    # 指定排序字段, 不设置, 排序功能不起效  ,最新:-pub_time, 最热:-study_num
    ordering_fields = ('pub_time', 'study_num')

    # 指定过滤字段, 不设置, 过滤功能不起效
    filter_fields = ('status', 'tag', 'fee')

    pagination_class = CoursePagination


class ChapterModelViewSet(ModelViewSet):
    queryset = Chapter.objects.all()
    serializer_class = ChapterModelSerializer


class SectionModelViewSet(ModelViewSet):
    queryset = Section.objects.all()
    serializer_class = SectionModelSerializer


class FollowModelViewSet(ModelViewSet):
    queryset = Follow.objects.all()
    serializer_class = FollowModelSerializer

    filter_fields = ('user', 'course')


class ChangeFollowAPIView(APIView):
    # 登录用户才能访问
    # 自定义权限类
    permission_classes = (IsAuthenticated,)  # 谁来处理权限认证的事情

    # 获取是否关注
    def get(self, request):
        # 1. 接收参数 username  cid
        username = request.GET.get('username')
        cid = request.GET.get('cid')
        # 2. 验证参数
        if all([username, cid]):
            pass
        else:
            return Response({'code': '999', 'msg': '缺少参数'})
        # 3. 查询是否关注
        count = Follow.objects.filter(user__username=username, course_id=cid).count()
        # 4. 返回结果
        return Response({'code': '0', 'msg': '查询成功', 'count': count})

    def post(self, request):
        # 1. 获取数据,  用户, 课程id, type: 1.关注 2.取消关注
        user = request.user  # 用户对象
        cid = request.data.get('cid')  # 课程id
        type = request.data.get('type')  # 类型
        # 2. 校验参数
        if all([user, cid, type]):
            pass
        else:
            return Response({'code': 999, 'msg': '缺少参数'})
        # 3. 更新数据
        count = Follow.objects.filter(user=user, course_id=cid).count()
        if type == '1':  # 关注
            if count > 0:
                pass
            else:
                follow = Follow.objects.create(user=user, course_id=cid)
                follow.course.attention_num += 1
                follow.course.save()
            return Response({'code': 0, 'msg': '已关注'})
        else:  # 取消关注
            if count > 0:
                follow = Follow.objects.filter(user=user, course_id=cid).first()
                follow.course.attention_num -= 1
                follow.course.save()
                follow.delete()
            else:
                pass
            return Response({'code': 0, 'msg': '已取消关注'})
        # 4. 返回响应


class UserCourseSectionAPIView(APIView):
    def get(self, request):
        # 1. sid, user
        user = request.user
        cid = request.GET.get('cid')  # post=> request.data   get=> request.GET

        # 2. 查用户看课程的记录
        try:
            ucs = UserCourseSection.objects.get(user=user, course_id=cid)
        except Exception as e:
            return Response({'code': '0', 'msg': '没有观看记录', 'section_ids': []})

        # 3. 返回
        sec_list = ucs.sections.split(',')
        sec_list.sort()
        return Response({'code': '0', 'msg': '查询成功', 'section_ids': sec_list})

    def post(self, request):
        # 1. 接收参数, sid,  user
        user = request.user
        sid = request.data.get('sid')  # post=> request.data   get=> request.GET

        # 2. 校验参数, a.有没有, b.判断小节id是否真实有效
        try:
            section = Section.objects.get(id=sid)
        except Exception as e:
            return Response({'code': '999', 'msg': '没有这个小节'})

        # 判断匿名用户
        if user.is_anonymous:
            return Response({'code': 0, 'msg': '成功', 'video_url': section.video.url, 'cid': section.chapter.course.id})

        # 3. 保存数据, a.给用户增加小节观看记录, b. 给课程增加观看次数(如果没有看过这个课程)
        course = section.chapter.course
        try:
            ucs = UserCourseSection.objects.get(user=user, course=course)
            section_set = set(ucs.sections.split(','))  # string

        except Exception as e:
            course.study_num += 1
            course.save()  # 给课程增加观看次数
            ucs = UserCourseSection.objects.create(user=user, course=course)
            section_set = set()

        # 小节列表, list?  set(因为小节不能重复)

        # 小节观看量增加
        section.play_num += 1
        section.save()

        # 更新观看记录
        section_set.add(sid)
        ucs.sections = ','.join(section_set)
        ucs.save()  # 更新最后观看时间

        # 4. 返回结果, 视频地址
        return Response({'code': 0, 'msg': '成功', 'video_url': section.video.url, 'cid': section.chapter.course.id})


class CourseSearchAPIView(APIView):
    def get(self, request):
        # 1. 获取参数,  kw,  关键词
        kw = request.GET.get('kw')
        if kw:
            pass
        else:
            return Response({'code': '999', 'msg': '缺少关键词'})
        # 2. 根据关键词, 从课程里查找
        # 2.1 模糊查找课程名  2.2 模糊查找课程简介
        # 课程名:  Linux
        # 关键词:  linux

        courses = Course.objects.filter(Q(title__icontains=kw) | Q(desc__icontains=kw))

        # 3. 序列化课程  # 4. 返回结果
        if len(courses) > 0:
            ser = CourseModelSerializer(courses, many=True)
            return Response({'code': '0', 'msg': 'ok', 'data': ser.data, 'count': len(courses)})
        else:
            return Response({'code': '0', 'msg': '没搜到课程', 'data': [], 'count': 0})


class CourseCommentModelViewSet(ModelViewSet):
    queryset = CourseComment.objects.all()
    serializer_class = CourseCommentModelSerializer

    filter_fields = ('course',)


class CommentAPIView(APIView):
    permission_classes = (IsAuthenticated,)

    def post(self, request):
        # 1. 获取数据,  user, cid 课程id, content 评论内容, to:给那个评论回复, 评论id
        user = request.user
        cid = request.data.get('cid')
        content = request.data.get('content')
        to = request.data.get('to')

        # 2. 校验数据
        if all([cid, content]):
            pass
        else:
            return Response({'code': '999', 'msg': '缺少参数'})

        try:
            course = Course.objects.get(id=cid)
        except Exception as e:
            return Response({'code': '999', 'msg': '课程不存在'})

        # 3. 保存数据
        CourseComment.objects.create(
            user=user,
            course=course,
            content=content,
            to_id=to if to else None)
        # 4. 返回结果
        return Response({'code': '0', 'msg': '评论成功'})


# re_path('media/video/(?P<filename>.*)', )
def MediaView(request, filename):
    # 访问  /media/video/1.mp4 开头的路径, => 返回视频内容
    # 1. 判断一下视频是不是vip视频, 小节id
    sid = request.GET.get('sid')
    token = request.GET.get('token')
    try:
        s = Section.objects.get(id=sid)
    except Exception as e:
        return HttpResponse(b'', content_type='video/mp4')
    # 视频是否是会员视频
    if s.chapter.course.fee != 3:
        abs_path = 'E:\\1.学习专用\\Python\\7.第七个月\\syl_1912\\syl\\media\\video\\'
        abs_file_path = abs_path + filename
        with open(abs_file_path, 'rb') as f:
            content = f.read()
        # 根据文件名, 读取文件内容, 返给前端
        return HttpResponse(content, content_type='video/mp4')
    # 2. 判断一下用户是不是vip用户
    # 解出token
    data = jwt_decode_handler(token)
    print(data)
    user_id = data.get('user_id')
    user = User.objects.get(id=user_id)
    if user.vip.level > 0:
        # 3. 符合要求就返回视频, 不符合就返回空
        print(filename)
        abs_path = 'E:\\1.学习专用\\Python\\7.第七个月\\syl_1912\\syl\\media\\video\\'
        abs_file_path = abs_path + filename
        with open(abs_file_path, 'rb') as f:
            content = f.read()
        # 根据文件名, 读取文件内容, 返给前端
        return HttpResponse(content, content_type='video/mp4')
    else:
        return HttpResponse(b'', content_type='video/mp4')
